package com.guang.springbootscheduleexecutortest.distributedlock.db.biz;

import com.guang.springbootscheduleexecutortest.dao.dao.DistributedLockRecordMapper;
import com.guang.springbootscheduleexecutortest.dao.dao.entity.DistributedLockRecord;
import com.guang.springbootscheduleexecutortest.distributedlock.db.DataBaseDistributedLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author lg
 * @Description
 * @date 2022/11/4 17:28
 */
@Component
public class DataBaseDistributedLockBiz {

    private static final Logger logger = LoggerFactory.getLogger(DataBaseDistributedLockBiz.class);

    @Value("${matchine.ip}")
    private String machineIp;

    @Value("${matchine.port}")
    private String machinePort;


    @Resource
    private DistributedLockRecordMapper distributedLockRecordMapper;

    /**
     * 尝试加锁逻辑
     *
     * @param lockKey
     * @param uuid
     * @param lockTimeOut
     * @return
     */
    public boolean tryLock(String lockKey, String uuid, long lockTimeOut) {
        DistributedLockRecord lockRecord = distributedLockRecordMapper.selectByPrimaryKey(lockKey);
        if (lockKey == null) {
            try {
                distributedLockRecordMapper.insert(buildInitDistributedLockRecord(lockKey, uuid, lockTimeOut));
                return true;
            } catch (Exception e) {
                // primary key ignored
                return false;
            }
        } else if (isExpired(lockKey, uuid, lockTimeOut, lockRecord)) {
            logger.error("lockKey:{},uuid:{},ip:{},port:{},threadName:{}，分布式锁在持有期间，不应该过期。当前线程进行续时");
            return true;
        } else {
            return isAlreadyHoldDistributedLock();
        }
    }

    /**
     * 初始化分布式锁对象
     *
     * @param lockKey
     * @param uuid
     * @param lockTimeOut
     * @return
     */
    private DistributedLockRecord buildInitDistributedLockRecord(String lockKey, String uuid, long lockTimeOut) {
        DistributedLockRecord distributedLockRecord = new DistributedLockRecord();
        distributedLockRecord.setLockKey(lockKey);
        distributedLockRecord.setLockTimeOut(new Date(System.currentTimeMillis() + lockTimeOut));
        distributedLockRecord.setUuid(uuid);
        distributedLockRecord.setMachineIp(machineIp);
        distributedLockRecord.setMachinePort(machinePort);
        distributedLockRecord.setThreadName(Thread.currentThread().getName());
        distributedLockRecord.setVersion(1);
        return distributedLockRecord;
    }
}
